home *** CD-ROM | disk | FTP | other *** search
- # this owns partitioning, fstab generation, disk scanning, raid, etc
- #
- # a fstab is returned as a list of:
- # ( mntpoint, device, fsystem, doFormat, size, (file) )
- # tuples, sorted by mntpoint; note that device may be a raid device; the file
- # value is optional, and if it exists it names a file which will be created
- # on the (already existant!) device and loopback mounted
- #
- # the swap information is stored as ( device, format ) tuples
- #
- # raid lists are stored as ( mntpoint, raiddevice, fssystem, doFormat,
- # raidlevel, [ device list ] )
- #
- # we always store as much of the fstab within the disk druid structure
- # as we can -- Don't Duplicate Data.
-
- import isys
- import iutil
- import os
- import string
- import raid
- import struct
- from translate import _
-
- def isValidExt2(device):
- file = '/tmp/' + device
- isys.makeDevInode(device, file)
- try:
- fd = os.open(file, os.O_RDONLY)
- except:
- return 0
-
- buf = os.read(fd, 2048)
- os.close(fd)
-
- if len(buf) != 2048:
- return 0
-
- if struct.unpack("H", buf[1080:1082]) == (0xef53,):
- return 1
-
- return 0
-
- class Fstab:
- def attemptPartitioning(self, partitions, clearParts):
- attempt = []
- swapCount = 0
-
- fstab = []
- for (mntpoint, dev, fstype, reformat, size) in self.extraFilesystems:
- fstab.append ((dev, mntpoint))
-
- ddruid = self.createDruid(fstab = fstab, ignoreBadDrives = 1)
-
- for (mntpoint, size, maxsize, grow, device) in partitions:
- type = 0x83
- if (mntpoint == "swap"):
- mntpoint = "Swap%04d-auto" % swapCount
- swapCount = swapCount + 1
- type = 0x82
- elif (mntpoint[0:5] == "raid."):
- type = 0xfd
-
- attempt.append((mntpoint, size, maxsize, type, grow, -1, device))
-
- try:
- ddruid.attempt (attempt, "Junk Argument", clearParts)
- return ddruid
- except:
- pass
-
- return None
-
- def getMbrDevice(self):
- return self.driveList()[0]
-
- def getBootDevice(self):
- bootDevice = None
- rootDevice = None
- for (mntpoint, partition, fsystem, doFormat, size) in self.mountList():
- if mntpoint == '/':
- rootDevice = partition
- elif mntpoint == '/boot':
- bootDevice = partition
-
- if not bootDevice:
- bootDevice = rootDevice
-
- return bootDevice
-
- def getRootDevice(self):
- for (mntpoint, partition, fsystem, doFormat, size) in self.mountList():
- if mntpoint == '/':
- return (partition, fsystem)
-
- def rootOnLoop(self):
- if not self.setupFilesystems: return 0
- for (mntpoint, partition, fsystem, doFormat, size) in self.mountList():
- if mntpoint == '/':
- if fsystem == "vfat":
- return 1
- else:
- return 0
-
- raise ValueError, "no root device has been set"
-
- def getLoopbackSize(self):
- return (self.loopbackSize, self.loopbackSwapSize)
-
- def setLoopbackSize(self, size, swapSize):
- self.loopbackSize = size
- self.loopbackSwapSize = swapSize
-
- def setDruid(self, druid, raid):
- self.ddruid = druid
- self.fsCache = {}
- for (mntPoint, raidDev, level, devices) in raid:
- if mntPoint == "swap":
- fsystem = "swap"
- else:
- fsystem = "ext2"
- self.addNewRaidDevice(mntPoint, raidDev, fsystem, level, devices)
-
- def rescanPartitions(self, clearFstabCache = 0):
- if self.ddruid:
- self.closeDrives(clearFstabCache)
-
- fstab = []
- for (mntpoint, dev, fstype, reformat, size) in self.cachedFstab:
- fstab.append ((dev, mntpoint))
-
- self.ddruid = self.fsedit(0, self.driveList(), fstab, self.zeroMbr,
- self.readOnly)
- del self.cachedFstab
-
- def closeDrives(self, clearFstabCache = 0):
- # we expect a rescanPartitions() after this!!!
- if clearFstabCache:
- self.cachedFstab = []
- else:
- self.cachedFstab = self.mountList(skipExtra = 1)
- self.ddruid = None
-
- def setReadonly(self, readOnly):
- self.readOnly = readOnly
- self.ddruid.setReadOnly(readOnly)
-
- def savePartitions(self):
- self.ddruid.save()
-
- def runDruid(self):
- rc = self.ddruid.edit()
- # yikes! this needs to be smarter
- self.beenSaved = 0
- return rc
-
- def updateFsCache(self):
- realFs = {}
- for (partition, mount, fsystem, size) in self.ddruid.getFstab():
- realFs[(partition, mount)] = 1
- for ((partition, mount)) in self.fsCache.keys():
- if not realFs.has_key((partition, mount)):
- del self.fsCache[(partition, mount)]
-
- def setFormatFilesystem(self, device, format):
- for (mntpoint, partition, fsystem, doFormat, size) in self.mountList():
- if partition == device:
- self.fsCache[(partition, mntpoint)] = (format,)
- return
-
- raise TypeError, "unknown partition to format %s" % (device,)
-
- def formatAllFilesystems(self):
- for (partition, mount, fsystem, size) in self.ddruid.getFstab():
- if mount[0] == '/':
- self.fsCache[(partition, mount)] = (1,)
- (devices, raid) = self.ddruid.partitionList()
- for (mount, partition, fsystem, level, i, j, deviceList) in \
- self.raidList()[1]:
- if mount[0] == '/':
- self.fsCache[(partition, mount)] = (1,)
-
- def partitionList(self):
- return self.ddruid.partitionList()
-
- def driveList(self):
- drives = isys.hardDriveDict().keys()
- drives.sort (isys.compareDrives)
- return drives
-
- def drivesByName(self):
- return isys.hardDriveDict()
-
- def swapList(self):
- fstab = []
- for (partition, mount, fsystem, size) in self.ddruid.getFstab():
- if fsystem != "swap": continue
-
- fstab.append((partition, 1))
-
- # Add raid mounts to mount list
- (devices, raid) = self.raidList()
- for (mntpoint, device, fsType, raidType, start, size, makeup) in raid:
- if fsType != "swap": continue
- fstab.append((device, 1))
-
- for n in self.extraFilesystems:
- (mntpoint, device, fsType, doFormat, size) = n
- if fsType != "swap": continue
- fstab.append((device, 1))
-
- return fstab
-
- def turnOffSwap(self):
- if not self.swapOn: return
- self.swapOn = 0
- for (device, doFormat) in self.swapList():
- file = '/tmp/swap/' + device
- isys.swapoff(file)
-
- def turnOnSwap(self, formatSwap = 1):
- # we could be smarter about this
- if self.swapOn or self.rootOnLoop(): return
- self.swapOn = 1
-
- iutil.mkdirChain('/tmp/swap')
-
- for (device, doFormat) in self.swapList():
- file = '/tmp/swap/' + device
- isys.makeDevInode(device, file)
-
- if formatSwap:
- w = self.waitWindow(_("Formatting"),
- _("Formatting swap space on /dev/%s...") %
- (device,))
-
- rc = iutil.execWithRedirect ("/usr/sbin/mkswap",
- [ "mkswap", '-v1', file ],
- stdout = None, stderr = None,
- searchPath = 1)
- w.pop()
-
- if rc:
- self.messageWindow(_("Error"), _("Error creating swap on device ") + device)
- else:
- isys.swapon (file)
- else:
- try:
- isys.swapon (file)
- except:
- # XXX should we complain?
- pass
-
- def addNewRaidDevice(self, mountPoint, raidDevice, fileSystem,
- raidLevel, deviceList):
- self.supplementalRaid.append((mountPoint, raidDevice, fileSystem,
- raidLevel, deviceList))
-
- def clearExistingRaid(self):
- self.existingRaid = []
-
- def addExistingRaidDevice(self, raidDevice, mntPoint, fsystem, deviceList):
- self.existingRaid.append(raidDevice, mntPoint, fsystem, deviceList)
-
- def existingRaidList(self):
- return self.existingRaid
-
- def raidList(self):
- (devices, raid) = self.ddruid.partitionList()
-
- if raid == None:
- raid = []
-
- for (mountPoint, raidDevice, fileSystem, raidLevel, deviceList) in \
- self.supplementalRaid:
- raid.append(mountPoint, raidDevice, fileSystem, raidLevel,
- 0, 0, deviceList)
-
- return (devices, raid)
-
- def createRaidTab(self, file, devPrefix, createDevices = 0):
- (devices, raid) = self.raidList()
-
- if not raid: return
-
- deviceDict = {}
- for (device, name, type, start, size) in devices:
- deviceDict[name] = device
-
- rt = open(file, "w")
- for (mntpoint, device, fstype, raidType, start, size, makeup) in raid:
-
- if createDevices:
- isys.makeDevInode(device, devPrefix + '/' + device)
-
- rt.write("raiddev %s/%s\n" % (devPrefix, device,))
- rt.write("raid-level %d\n" % (raidType,))
- rt.write("nr-raid-disks %d\n" % (len(makeup),))
- rt.write("chunk-size 64k\n")
- rt.write("persistent-superblock 1\n");
- rt.write("#nr-spare-disks 0\n")
- i = 0
- for subDevName in makeup:
- isys.makeDevInode(deviceDict[subDevName], '%s/%s' %
- (devPrefix, deviceDict[subDevName]))
- rt.write(" device %s/%s\n" %
- (devPrefix, deviceDict[subDevName],))
- rt.write(" raid-disk %d\n" % (i,))
- i = i + 1
-
- rt.write("\n")
- rt.close()
-
- def umountFilesystems(self, instPath, ignoreErrors = 0):
- if (not self.setupFilesystems): return
-
- isys.umount(instPath + '/proc')
-
- mounts = self.mountList()
- mounts.reverse()
- for (n, device, fsystem, doFormat, size) in mounts:
- if fsystem != "swap":
- try:
- mntPoint = instPath + n
- isys.umount(mntPoint)
- except SystemError, (errno, msg):
- if not ignoreErrors:
- self.messageWindow(_("Error"),
- _("Error unmounting %s: %s") % (device, msg))
-
- if self.rootOnLoop():
- isys.makeDevInode("loop0", '/tmp/' + "loop0")
- isys.unlosetup("/tmp/loop0")
-
- for (raidDevice, mntPoint, fileSystem, deviceList) in self.existingRaid:
- isys.raidstop(raidDevice)
-
- def makeFilesystems(self):
- # let's make the RAID devices first -- the fstab will then proceed
- # naturally
- (devices, raid) = self.raidList()
-
- if self.serial:
- messageFile = "/tmp/mke2fs.log"
- else:
- messageFile = "/dev/tty5"
-
- if raid:
- self.createRaidTab("/tmp/raidtab", "/tmp", createDevices = 1)
-
- w = self.waitWindow(_("Creating"), _("Creating RAID devices..."))
-
- for (mntpoint, device, fsType, raidType, start, size, makeup) in raid:
- iutil.execWithRedirect ("/usr/sbin/mkraid",
- [ 'mkraid', '--really-force', '--configfile',
- '/tmp/raidtab', '/tmp/' + device ],
- stderr = messageFile, stdout = messageFile)
-
- w.pop()
-
- # XXX remove extraneous inodes here
- # print "created raid"
-
- if not self.setupFilesystems: return
-
- arch = iutil.getArch ()
-
- if arch == "alpha":
- bootPart = self.getBootDevice()
-
- for (mntpoint, device, fsystem, doFormat, size) in self.mountList():
- if not doFormat: continue
- isys.makeDevInode(device, '/tmp/' + device)
- if fsystem == "ext2":
- args = [ "mke2fs", '/tmp/' + device ]
- # FORCE the partition that MILO has to read
- # to have 1024 block size. It's the only
- # thing that our milo seems to read.
- if arch == "alpha" and device == bootPart:
- args = args + ["-b", "1024", '-r', '0', '-O', 'none']
- # set up raid options for md devices.
- if device[:2] == 'md':
- for (rmnt, rdevice, fsType, raidType, start, size, makeup) in raid:
- if rdevice == device:
- rtype = raidType
- rdisks = len (makeup)
- if rtype == 5:
- rdisks = rdisks - 1
- args = args + [ '-R', 'stride=%d' % (rdisks * 16) ]
- elif rtype == 0:
- args = args + [ '-R', 'stride=%d' % (rdisks * 16) ]
-
- if self.badBlockCheck:
- args.append ("-c")
-
- w = self.waitWindow(_("Formatting"),
- _("Formatting %s filesystem...") % (mntpoint,))
-
- iutil.execWithRedirect ("/usr/sbin/mke2fs",
- args, stdout = messageFile,
- stderr = messageFile, searchPath = 1)
- w.pop()
- else:
- pass
-
- os.remove('/tmp/' + device)
-
- def mountFilesystems(self, instPath):
- if (not self.setupFilesystems): return
-
- for (raidDevice, mntPoint, fileSystem, deviceList) in self.existingRaid:
- isys.raidstart(raidDevice, deviceList[0])
-
- for (mntpoint, device, fsystem, doFormat, size) in self.mountList():
- if fsystem == "swap":
- continue
- elif fsystem == "vfat" and mntpoint == "/":
- # do a magical loopback mount -- whee!
- w = self.waitWindow(_("Loopback"),
- _("Creating loopback filesystem on device /dev/%s...") % (device,))
-
- iutil.mkdirChain("/mnt/loophost")
- isys.makeDevInode(device, '/tmp/' + device)
- isys.mount('/tmp/' + device, "/mnt/loophost", fstype = "vfat")
- os.remove( '/tmp/' + device);
-
- isys.makeDevInode("loop0", '/tmp/' + "loop0")
- isys.ddfile("/mnt/loophost/redhat.img", self.loopbackSize)
- isys.losetup("/tmp/loop0", "/mnt/loophost/redhat.img")
-
- if self.serial:
- messageFile = "/tmp/mke2fs.log"
- else:
- messageFile = "/dev/tty5"
-
- iutil.execWithRedirect ("/usr/sbin/mke2fs",
- [ "mke2fs", "/tmp/loop0" ],
- stdout = messageFile,
- stderr = messageFile, searchPath = 1)
-
- isys.mount('/tmp/loop0', instPath)
- os.remove('/tmp/loop0')
-
- if self.loopbackSwapSize:
- isys.ddfile("/mnt/loophost/rh-swap.img",
- self.loopbackSwapSize)
- iutil.execWithRedirect ("/usr/sbin/mkswap",
- [ "mkswap", '-v1',
- '/mnt/loophost/rh-swap.img' ],
- stdout = None, stderr = None)
- isys.swapon("/mnt/loophost/rh-swap.img")
-
- w.pop()
- elif fsystem == "ext2":
- try:
- iutil.mkdirChain(instPath + mntpoint)
- isys.makeDevInode(device, '/tmp/' + device)
- isys.mount('/tmp/' + device,
- instPath + mntpoint)
- os.remove( '/tmp/' + device);
- except SystemError, (errno, msg):
- self.messageWindow(_("Error"),
- _("Error mounting %s: %s") % (device, msg))
- raise SystemError, (errno, msg)
-
- try:
- os.mkdir (instPath + '/proc')
- except:
- pass
-
- isys.mount('/proc', instPath + '/proc', 'proc')
-
- def write(self, prefix, fdDevice = "/dev/fd0"):
- format = "%-23s %-23s %-7s %-15s %d %d\n";
-
- f = open (prefix + "/etc/fstab", "w")
- for (mntpoint, dev, fs, reformat, size) in self.mountList():
- if fs == "vfat" and mntpoint == "/":
- f.write("# LOOP0: /dev/%s %s /redhat.img\n" % (dev, fs))
- dev = "loop0"
- fs = "ext2"
-
- iutil.mkdirChain(prefix + mntpoint)
- if mntpoint == '/':
- f.write (format % ( '/dev/' + dev, mntpoint, fs, 'defaults', 1, 1))
- else:
- if fs == "ext2":
- f.write (format % ( '/dev/' + dev, mntpoint, fs, 'defaults', 1, 2))
- elif fs == "iso9660":
- f.write (format % ( '/dev/' + dev, mntpoint, fs, 'noauto,owner,ro', 0, 0))
- elif fs == "auto" and (dev == "zip" or dev == "jaz"):
- f.write (format % ( '/dev/' + dev, mntpoint, fs, 'noauto,owner', 0, 0))
- else:
- f.write (format % ( '/dev/' + dev, mntpoint, fs, 'defaults', 0, 0))
- f.write (format % (fdDevice, "/mnt/floppy", 'auto', 'noauto,owner', 0, 0))
- f.write (format % ("none", "/proc", 'proc', 'defaults', 0, 0))
- f.write (format % ("none", "/dev/pts", 'devpts', 'gid=5,mode=620', 0, 0))
-
- if self.loopbackSwapSize:
- f.write(format % ("/initrd/loopfs/rh-swap.img", 'swap',
- 'swap', 'defaults', 0, 0))
-
- for (partition, doFormat) in self.swapList():
- f.write (format % ("/dev/" + partition, 'swap', 'swap',
- 'defaults', 0, 0))
-
- f.close ()
- # touch mtab
- open (prefix + "/etc/mtab", "w+")
- f.close ()
-
- self.createRaidTab(prefix + "/etc/raidtab", "/dev")
-
- def clearMounts(self):
- self.extraFilesystems = []
-
- def addMount(self, partition, mount, fsystem, doFormat = 0, size = 0):
- self.extraFilesystems.append(mount, partition, fsystem, doFormat,
- size)
- # XXX code from sparc merge
- # if fsystem == "swap":
- # ufs = 0
- # try:
- # isys.makeDevInode(device, '/tmp/' + device)
- # except:
- # pass
- # try:
- # ufs = isys.checkUFS ('/tmp/' + device)
- # except:
- # pass
- # if not ufs:
- # location = "swap"
- # reformat = 1
- # self.mounts[location] = (device, fsystem, reformat)
-
-
- def mountList(self, skipExtra = 0):
- def sortMounts(one, two):
- mountOne = one[0]
- mountTwo = two[0]
- if (mountOne < mountTwo):
- return -1
- elif (mountOne == mountTwo):
- return 0
- return 1
-
- fstab = []
- for (partition, mount, fsystem, size) in self.ddruid.getFstab():
- if fsystem == "swap": continue
-
- if not self.fsCache.has_key((partition, mount)):
- if mount == '/home' and isValidExt2(partition):
- self.fsCache[(partition, mount)] = (0, )
- else:
- self.fsCache[(partition, mount)] = (1, )
- (doFormat,) = self.fsCache[(partition, mount)]
- fstab.append((mount, partition, fsystem, doFormat, size ))
-
- for (raidDevice, mntPoint, fsType, deviceList) in self.existingRaid:
- if fsType == "swap": continue
-
- fstab.append((mntPoint, raidDevice, fsType, 0, 0 ))
-
- # Add raid mounts to mount list
- (devices, raid) = self.raidList()
- for (mntpoint, device, fsType, raidType, start, size, makeup) in raid:
- if fsType == "swap": continue
-
- if not self.fsCache.has_key((device, mntpoint)):
- self.fsCache[(device, mntpoint)] = (1, )
- (doFormat,) = self.fsCache[(device, mntpoint)]
- fstab.append((mntpoint, device, fsType, doFormat, size ))
-
- if not skipExtra:
- for n in self.extraFilesystems:
- (mntpoint, sevice, fsType, doFormat, size) = n
- if fsType == "swap": continue
- fstab.append(n)
-
- fstab.sort(sortMounts)
-
- return fstab
-
- def saveDruidPartitions(self):
- if self.beenSaved: return
- self.ddruid.save()
- self.beenSaved = 1
-
- def setBadBlockCheck(self, state):
- self.badBlockCheck = state
-
- def getBadBlockCheck(self):
- return self.badBlockCheck
-
- def createDruid(self, fstab = [], ignoreBadDrives = 0):
- return self.fsedit(0, self.driveList(), fstab, self.zeroMbr,
- self.readOnly, ignoreBadDrives)
-
- def getRunDruid(self):
- return self.shouldRunDruid
-
- def setRunDruid(self, state):
- self.shouldRunDruid = state
-
- def __init__(self, fsedit, setupFilesystems, serial, zeroMbr,
- readOnly, waitWindow, messageWindow):
- self.fsedit = fsedit
- self.fsCache = {}
- self.swapOn = 0
- self.supplementalRaid = []
- self.beenSaved = 1
- self.setupFilesystems = setupFilesystems
- self.serial = serial
- self.zeroMbr = zeroMbr
- self.readOnly = readOnly
- self.waitWindow = waitWindow
- self.messageWindow = messageWindow
- self.badBlockCheck = 0
- self.extraFilesystems = []
- self.existingRaid = []
- self.ddruid = self.createDruid()
- self.loopbackSize = 0
- self.loopbackSwapSize = 0
- # I intentionally don't initialize this, as all install paths should
- # initialize this automatically
- #self.shouldRunDruid = 0
-
- class GuiFstab(Fstab):
- def accel (self, widget, area):
- self.accelgroup = self.GtkAccelGroup (_obj = widget.get_data ("accelgroup"))
- self.toplevel = widget.get_toplevel()
- self.toplevel.add_accel_group (self.accelgroup)
-
- def runDruid(self, callback):
- self.ddruid.setCallback (callback)
- bin = self.GtkFrame (None, _obj = self.ddruid.getWindow ())
- bin.connect ("draw", self.accel)
- bin.set_shadow_type (self.SHADOW_NONE)
- self.ddruid.edit ()
- return bin
-
- def runDruidFinished(self):
- if self.accelgroup:
- self.toplevel.remove_accel_group (self.accelgroup)
- self.ddruid.next ()
- self.updateFsCache()
- # yikes! this needs to be smarter
- self.beenSaved = 0
-
- def __init__(self, setupFilesystems, serial, zeroMbr, readOnly, waitWindow,
- messageWindow):
- from gnomepyfsedit import fsedit
- from gtk import *
-
- Fstab.__init__(self, fsedit, setupFilesystems, serial, zeroMbr,
- readOnly, waitWindow, messageWindow)
-
- self.GtkFrame = GtkFrame
- self.GtkAccelGroup = GtkAccelGroup
- self.SHADOW_NONE = SHADOW_NONE
- self.accelgroup = None
-
- class NewtFstab(Fstab):
-
- def __init__(self, setupFilesystems, serial, zeroMbr, readOnly, waitWindow,
- messageWindow):
- from newtpyfsedit import fsedit
-
- Fstab.__init__(self, fsedit, setupFilesystems, serial, zeroMbr,
- readOnly, waitWindow, messageWindow)
-
- def readFstab (path, fstab):
- f = open (path, "r")
- lines = f.readlines ()
- f.close
-
- fstab.clearExistingRaid()
- fstab.clearMounts()
-
- drives = fstab.driveList()
- raidList = raid.scanForRaid(drives)
- raidByDev = {}
- for (mdDev, devList) in raidList:
- raidByDev[mdDev] = devList
-
- for line in lines:
- fields = string.split (line)
- # skip comments
- if fields and fields[0][0] == '#':
- continue
- if not fields: continue
- # all valid fstab entries have 6 fields
- if len (fields) < 4 or len (fields) > 6: continue
-
- if fields[2] != "ext2" and fields[2] != "swap": continue
- if string.find(fields[3], "noauto") != -1: continue
- if (fields[0][0:7] != "/dev/hd" and
- fields[0][0:7] != "/dev/sd" and
- fields[0][0:7] != "/dev/md" and
- fields[0][0:8] != "/dev/rd/" and
- fields[0][0:9] != "/dev/ida/"): continue
-
- if fields[0][0:7] == "/dev/md":
- fstab.addExistingRaidDevice(fields[0][5:], fields[1],
- fields[2], raidByDev[int(fields[0][7:])])
- else:
- fstab.addMount(fields[0][5:], fields[1], fields[2])
-